package com.heima.comment.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.heima.apis.user.IUserClient;
import com.heima.comment.pojos.ApComment;
import com.heima.comment.pojos.ApCommentLike;
import com.heima.comment.service.CommentService;
import com.heima.common.constants.CommentConstants;
import com.heima.common.exception.CustomException;
import com.heima.common.redis.CacheService;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.thread.ApThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author yht
 * @date 2022/1/22 14:37
 */
@Service
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private IUserClient iUserClient;
    @Autowired
    private CacheService cacheService;

    /**
     * 保存评论
     * @param commentSaveDto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDto commentSaveDto) {
        ApUser user = ApThreadLocalUtils.getUser();
        if(ObjectUtil.isEmpty(user)){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        if(ObjectUtil.isEmpty(commentSaveDto)){
            log.error("保存评论缺少参数");
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //根据id远程调用查询用户信息
        ResponseResult userById = iUserClient.findUserById(Long.parseLong(String.valueOf(user.getId())));
        if(userById.getCode()!=200){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"远程调用user模块出错:"+userById.getErrorMessage());
        }
        ApUser apUser = JSON.parseObject(String.valueOf(userById.getData()), ApUser.class);
        ApComment apComment=new ApComment();
        apComment.setAuthorId(apUser.getId());
        apComment.setAuthorName(apUser.getName());
        apComment.setEntryId(commentSaveDto.getArticleId());
        apComment.setType(0);
        apComment.setContent(commentSaveDto.getContent());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setFlag(0);
        apComment.setCreatedTime(new Date());
        ApComment comment = mongoTemplate.save(apComment);
        //先把评论数和点赞数保存在redis中
        cacheService.hPut(CommentConstants.COMMENT_LIKE_REDISKEY+comment.getId()
                ,CommentConstants.COMMENT_LIKE_COUNT,String.valueOf(0));
        cacheService.hPut(CommentConstants.COMMENT_LIKE_REDISKEY+comment.getId()
                ,CommentConstants.COMMENT_REPLY_COUNT,String.valueOf(0));
        return ResponseResult.okResult(comment);
    }

    /**
     * 评论点赞
     * @param commentLikeDto
     * @return
     */
    @Override
    public ResponseResult commentLike(CommentLikeDto commentLikeDto) {
        Integer count=0;
        ApUser user = ApThreadLocalUtils.getUser();
        if(ObjectUtil.isEmpty(user)){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        if(ObjectUtil.isEmpty(commentLikeDto)){
            log.error("保存评论缺少参数");
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //Operation=0点赞    1取消点赞
        if(commentLikeDto.getOperation()==0){
            boolean flag = isLike(CommentConstants.COMMENT_LIKE_REDISKEY+commentLikeDto.getCommentId(),
                    CommentConstants.LIKE_USER+user.getId());
            if(flag){
                return ResponseResult.okResult(cacheService.hGet(CommentConstants.COMMENT_LIKE_REDISKEY+commentLikeDto.getCommentId(),
                        CommentConstants.COMMENT_LIKE_COUNT));
            }
            //1点赞
            //1.1保存数据库
            ApCommentLike apCommentLike=new ApCommentLike();
            apCommentLike.setCommentId(commentLikeDto.getCommentId());
            apCommentLike.setAuthorId(user.getId());
            ApCommentLike commentLike = mongoTemplate.save(apCommentLike);
            //1.1修改点赞数
            //查询comment数据
            ApComment apComment = findCommentById(commentLikeDto.getCommentId());
            //修改mongo中的评论点赞数量
            count = apComment.getLikes()+1;
            apComment.setLikes(count);
            mongoTemplate.save(apComment);
            //2.修改redis中的数据
            //2.1保存redis用户点赞操作标识
            cacheService.hPut(CommentConstants.COMMENT_LIKE_REDISKEY+commentLikeDto.getCommentId(),
                    CommentConstants.LIKE_USER+user.getId(),
                    String.valueOf(0));
            //2.2修改redis中的点赞数量
            cacheService.hPut(CommentConstants.COMMENT_LIKE_REDISKEY+commentLikeDto.getCommentId(),
                    CommentConstants.COMMENT_LIKE_COUNT,
                    String.valueOf(count));

        } else if (commentLikeDto.getOperation()==1){
            boolean flag = isLike(CommentConstants.COMMENT_LIKE_REDISKEY+commentLikeDto.getCommentId(),
                    CommentConstants.LIKE_USER+user.getId());
            if(!flag){
                return ResponseResult.okResult(cacheService.hGet(CommentConstants.COMMENT_LIKE_REDISKEY+commentLikeDto.getCommentId(),
                        CommentConstants.COMMENT_LIKE_COUNT));
            }
            //取消点赞
            //1.根据用户id和评论的id去删除mongo中的数据
            Query query=new Query(Criteria.where("commentId").is(commentLikeDto.getCommentId())
                    .and("authorId").is(user.getId()));
            mongoTemplate.remove(query,ApCommentLike.class);
            //1.2 删除redis中用户的点赞标识
            cacheService.hDelete(CommentConstants.COMMENT_LIKE_REDISKEY+commentLikeDto.getCommentId(),
                    CommentConstants.LIKE_USER+user.getId());
            //2.修改数据库中的点赞数量
            ApComment comment = findCommentById(commentLikeDto.getCommentId());
            //取消点赞后的数量
            count=comment.getLikes()-1;
            comment.setLikes(count);
            //修改点赞后的数据
            mongoTemplate.save(comment);
            //2.2修改redis中的点赞数量
            cacheService.hPut(CommentConstants.COMMENT_LIKE_REDISKEY+ commentLikeDto.getCommentId(),
                    CommentConstants.COMMENT_LIKE_COUNT,
                    String.valueOf(count));
        }else {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        return ResponseResult.okResult(count);
    }

    /**
     * 查询评论
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findComment(CommentDto dto) {
        if(ObjectUtil.isEmpty(dto)){
            PageResponseResult pageResponseResult=new PageResponseResult();
            pageResponseResult.setErrorMessage("参数为空");
            return pageResponseResult;
        }
        Integer userId = ApThreadLocalUtils.getUser().getId();
        //分页查询数据，大于最后一条评论的时间，正序排序，每次查10条
        if(dto.getMinDate()==null){
            dto.setMinDate(new Date());
        }
        Query query=new Query(Criteria.where("entryId").is(dto.getArticleId()).and("createdTime").lt(dto.getMinDate())).with(Sort.by(Sort.Order.desc("createdTime"))).limit(10);
        List<ApComment> apComments = mongoTemplate.find(query, ApComment.class);
        //分装返回结果
        List<ApCommentVo> commentVos=new ArrayList<>();
        for (ApComment apComment : apComments) {
            ApCommentVo apCommentVo=new ApCommentVo();
            BeanUtil.copyProperties(apComment,apCommentVo);
            boolean flag= isLike(CommentConstants.COMMENT_LIKE_REDISKEY + apCommentVo.getId(),
                    CommentConstants.LIKE_USER + userId);
            if(!flag){
                apCommentVo.setOperation(null);
            }else {
                apCommentVo.setOperation(0);
            }

            commentVos.add(apCommentVo);
        }

        return ResponseResult.okResult(commentVos);
    }

    /**
     * 根据id查询mongo中的comment的数据
     * @param commentId
     */
    @Override
    public ApComment findCommentById(String commentId) {
        Query query=new Query(Criteria.where("id").is(commentId));
        List<ApComment> apComments = mongoTemplate.find(query, ApComment.class);
        if(ObjectUtil.isEmpty(apComments)){
            log.error("MongoDB数据不存在 id：{}",commentId);
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
       return apComments.get(0);
    }

    /**
     * 查询redis中是否有
     * @param redisKey
     * @param hashKey
     * @return
     */
    public boolean isLike(String redisKey,String hashKey){
       return cacheService.hExists(redisKey,hashKey);
    }

}
